package com.tensai.core.mvc.base.service.imp;

import com.tensai.core.mvc.base.dao.IBaseDao;
import com.tensai.core.mvc.base.entry.BaseEntity;
import com.tensai.core.mvc.base.service.IBaseService;
import com.tensai.core.mvc.base.tools.HqlFilter;
import com.tensai.core.mvc.base.tools.PageInfo;
import com.tensai.core.mvc.base.tools.ResultJson;
import com.tensai.core.constant.ResponseStatus;
import com.tensai.core.mvc.system.entry.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;

/**
 * 基础Service类，ID和UUID service类必须继承此类
 *
 * @author Tensai
 * 2018-03-09 15:46
 */
@Service
public abstract class BaseServiceImpl<T extends BaseEntity, IDType extends Serializable, K extends IBaseDao<T, IDType>> implements IBaseService<T, IDType> {

    /**
     * 注入的HttpSession用于获取当前用户
     */
    @Autowired
    private HttpSession httpSession;

    /**
     * 获取实现类的Dao层方法
     *
     * @return dao
     */
    protected abstract K getDao();

    /**
     * 分页信息
     *
     * @param page   分页
     * @param filter 过滤规则
     * @return 结果集
     */
    @Override
    public Page<T> page(PageInfo page, HqlFilter<T> filter) {
        return getDao().findAll(filter.getSpecification(), page.toPageable());
    }

    /**
     * 根据主键查找
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    public T findOne(IDType id) {
        if (id == null || ("").equals(id)) {
            return null;
        }
        return getDao().findOne(id);
    }

    /**
     * 根据逐渐删除实体
     *
     * @param id 主键
     * @return 操作状态
     */
    @Override
    public ResultJson delete(IDType id) {
        getDao().delete(id);
        return new ResultJson(ResponseStatus.DELETE_SUCCESS);
    }

    /**
     * 删除实体
     *
     * @param t 实体
     * @return 操作状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultJson delete(T t) {
        getDao().delete(t);
        return new ResultJson(ResponseStatus.DELETE_SUCCESS);
    }

    /**
     * 查询所有的数据
     *
     * @return 结果集
     */
    @Override
    public List<T> findAll() {
        return getDao().findAll();
    }

    /**
     * 获取当前用户
     *
     * @return 当前用户
     */
    public SysUser getCurrentUser() {
        return (SysUser) httpSession.getAttribute("currentUser");
    }

    /**
     * 该方法是用于相同对象不同属性值的合并，如果两个相同对象中同一属性都有值，那么sourceBean中的值会覆盖tagetBean重点的值
     *
     * @param sourceBean 被提取的对象bean
     * @param targetBean 用于合并的对象bean
     * @return targetBean, 合并后的对象
     */
    public T combineSydwCore(T sourceBean, T targetBean) {
        Class sourceBeanClass = sourceBean.getClass();
        Class targetBeanClass = targetBean.getClass();

        Field[] sourceFields = sourceBeanClass.getDeclaredFields();
        Field[] targetFields = targetBeanClass.getDeclaredFields();
        for (int i = 0; i < sourceFields.length; i++) {
            Field sourceField = sourceFields[i];
            if (Modifier.isStatic(sourceField.getModifiers())) {
                continue;
            }
            Field targetField = targetFields[i];
            if (Modifier.isStatic(targetField.getModifiers())) {
                continue;
            }
            sourceField.setAccessible(true);
            targetField.setAccessible(true);
            try {
                if (targetField.get(targetBean) == null && sourceField.get(sourceBean) != null && !"serialVersionUID".equals(sourceField.getName())) {
                    targetField.set(targetBean, sourceField.get(sourceBean));
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return targetBean;
    }
}
